#pragma once
#include <iostream>
#include "Socket.hpp"
#include "log.hpp"
#include <pthread.h>
class HttpServer;
const std::string wwwroot = "./wwwroot"; // web根目录
const std::string sep = "\r\n";
const std::string homepage = "/index.html";
class ThreadData
{
public:
    ThreadData(int _fd, HttpServer *it = nullptr) : fd(_fd), ts(it)
    {
    }
    int Getfd() { return fd; }

private:
    int fd;
    HttpServer *ts;
};
class HttpRequest
{

public:
    void Deser(string str)
    {
        int pos1 = 0, pos2 = 0;
        while (true)
        {
            int pos = str.find(sep);
            if (pos == string::npos) break;
            string temp = str.substr(0, pos);
            if (temp.empty()) break;
            vstr.push_back(temp);

            str.erase(0, pos + sep.size()); // 0处.删除pos + seq.size()个字符
            // 123/r/n
        }
        text = str;

        Parse();
    }
    void Print()
    {
        std::cout << "------------------------------------------" << endl;
        for (const auto &e : vstr)
        {
            cout << e << "\n\n";
        }
        std::cout << text << endl;
        cout << "---------------------------------------" << endl;
        cout << "Method: " << method << endl;
        cout << "url: " << url << endl;
        cout << "http_version: " << http_version << endl;
        cout << "_path" << _path << endl;
        cout <<"suff" << suff << endl;
    }
    void Parse()
    {
        // GET / HTTP/1.1
        stringstream s(vstr[0]);
        s >> method >> url >> http_version;
        _path = wwwroot;
        if (url == "/" || url == "/index.html")  _path += homepage;
        else _path += url;

        int pos = url.rfind('.');
        if(pos == string::npos) suff = "text/html";
        if(url.substr(pos + 1) == "png") suff = "imag/png";
    }
    string GetSuff()
    {
        suff += "\r\n";
        return suff;
    }
    vector<string> vstr;
    string text;
    string url;
    string http_version;
    string method;
    string _path;


    string suff;
};
class HttpServer
{
public:
    HttpServer(int port = 9192)
        : _port(port)
    {
    }
    bool Start()
    {
        sock.CreateSocket();
        sock.Bind(_port);
        sock.Listen();
        for (;;)
        {
            std::string ip;
            uint16_t port;
            int socketfd = sock.Accept(&ip, &port);
            if (socketfd < 0)
                return false;
            ThreadData *td = new ThreadData(socketfd);
            pthread_t tid;
            pthread_create(&tid, nullptr, ThreadRun, (void *)td);
        }

        return true;
    }
    static string ReadHtml(const string &str)
    {
        ifstream in(str);
        if (!in.is_open()) return "";
        // std::string line, content;
        // while (getline(in, line))
        // {
        //     content += line;
        // }
        // in.close();

        in.seekg(0,std::ios_base::end);
        auto len = in.tellg();
        in.seekg(0,std::ios_base::beg);
        std::string content;
        content.resize(len);

        in.read((char*)content.c_str(),content.size());
        return content;
        //eturn content;
    }
    static void HandlerHttp(int fd)
    {
        char buff[1024];
        ssize_t n = recv(fd, buff, sizeof(buff) - 1, 0);
        if (n > 0)
        {
            buff[n] = 0;
            std::cout << buff; // 假设我们读取到的是一个完整的、独立的http请求

            HttpRequest rq;
            rq.Deser(buff);
             rq.Print();
            // 返回响应的过程
            bool ok = 1;
            std::string text = ReadHtml(rq._path);
            if (text.empty())
            {
                std::string err_html = wwwroot;
                err_html += "/err.html";
                text = ReadHtml(err_html);
                ok = false;
            }
            
            std::string res;
            if(ok) res = "HTTP/1.0 200 OK\r\n";
            else res = "HTTP/1.0 404 Not Found\r\n";

           // res = "HTTP/1.0 302 Found\r\n";
            std::string res_header = "Content-Length: ";
            res_header += std::to_string(text.size());
            res_header += "\r\n";
            std::string block = "\r\n";
            res_header += "Location: https://www.baidu.com\r\n";
            res_header += "Content-Type: "; //类型 image/png text/html
            //Http响应如何获取Html中的图片?? 
            //1.获取图片也是一个响应, 实际上是GET /xxx/image/xxx.png
            //2.状态报头里面需要添加 Content-Type信息,确保拿到的是.html还是.png
            //3.在ReadHtml不能按行读取,那样无法读取二进制，要换成read
            res_header += rq.GetSuff();
           res_header += "Set-Cookie: name=hhh&&passwd=123456\r\n";
            string r = res;  // res状态行
            r += res_header; // 响应报头
            r += block;      // 空行
            r += text;       // 正文

            // 构建响应并发送回去
            send(fd, r.c_str(), r.size(), 0);
        }
        close(fd);
    }
    static void *ThreadRun(void *args)
    {
        pthread_detach(pthread_self());
        auto it = static_cast<ThreadData *>(args);
        HandlerHttp(it->Getfd());
        delete it;
        return nullptr;
    }
    ~HttpServer()
    {
    }

private:
    uint16_t _port;
    Socket sock;
};